
//------------------------ Matrix4 ------------------------------
/**
 * @class
 * @param {Matrix4} templent 被拷贝对象(可有可无)
 */
 export var Matrix4 = function( templent){
    var i,s,d;
    if(templent&& typeof templent === 'object' && templent.hasOwnProperty('elements')){
        s=templent.elements;
        d=new Float32Array(16);
        for(i=0;i<s.length;i++){
            d[i]=s[i]
        }
        
    }else{
        d=new Float32Array([
            1,0,0,0,
            0,1,0,0, 
            0,0,1,0, 
            0,0,0,1])
    }
    this.elements=d;
}
/**
 * 正交模型矩阵设置
 * @param {number} left     左边距离
 * @param {number} right    右边距离
 * @param {number} bottom   下面距离  
 * @param {number} top      上面距离
 * @param {number} near     前面距离
 * @param {number} far      后面距离
 * @returns 
 */
Matrix4.prototype.setOrtho = function(left, right, bottom, top, near, far) {
    var e, rw, rh, rd;
    if (left === right || bottom === top || near === far) {
      throw 'null frustum';
    }
    rw = 1 / (right - left);
    rh = 1 / (top - bottom);
    rd = 1 / (far - near);
  
    e = this.elements;
  
    e[0]  = 2 * rw;  e[4]  = 0;       e[8]  = 0;        e[12] = -(right + left) * rw;
    e[1]  = 0;       e[5]  = 2 * rh;  e[9]  = 0;        e[13] = -(top + bottom) * rh;
    e[2]  = 0;       e[6]  = 0;       e[10] = -2 * rd;  e[14] = -(far + near) * rd;
    e[3]  = 0;       e[7]  = 0;       e[11] = 0;        e[15] = 1;
    return this;
};
/**
* 从右边乘以矩阵。
* @param  other The multiply matrix
* @return this
*/
Matrix4.prototype.concat = function(other) {
 var i, e, a, b, ai0, ai1, ai2, ai3;
 
 // Calculate e = a * b
 e = this.elements;
 a = this.elements;
 b = other.elements;
 
 // If e equals b, copy b to temporary matrix.
 if (e === b) {
   b = new Float32Array(16);
   for (i = 0; i < 16; ++i) {
     b[i] = e[i];
   }
 }
 
 for (i = 0; i < 4; i++) {
   ai0=a[i];  ai1=a[i+4];  ai2=a[i+8];  ai3=a[i+12];
   e[i]    = ai0 * b[0]  + ai1 * b[1]  + ai2 * b[2]  + ai3 * b[3];
   e[i+4]  = ai0 * b[4]  + ai1 * b[5]  + ai2 * b[6]  + ai3 * b[7];
   e[i+8]  = ai0 * b[8]  + ai1 * b[9]  + ai2 * b[10] + ai3 * b[11];
   e[i+12] = ai0 * b[12] + ai1 * b[13] + ai2 * b[14] + ai3 * b[15];
 }
 return this;
};
/**
 * 乘以三维向量
 * @param {Vector3} pos  向量
 * @return {Vector3} resouces
 */
 Matrix4.prototype.multiplyVector3 = function(pos) {
    var e = this.elements;
    var p = pos.elements;
    var v = new Vector3();
  
    v.x = p[0] * e[0] + p[1] * e[4] + p[2] * e[ 8] + e[11];
    v.y = p[0] * e[1] + p[1] * e[5] + p[2] * e[ 9] + e[12];
    v.z = p[0] * e[2] + p[1] * e[6] + p[2] * e[10] + e[13];
  
    return v;
  };
/**
 * 乘以矩阵从右边缩放
 * @param x The scale factor along the X axis
 * @param y The scale factor along the Y axis
 * @param z The scale factor along the Z axis
 * @return this
 */
 Matrix4.prototype.scale = function(x, y, z) {
    var e = this.elements;
    e[0] *= x;  e[4] *= y;  e[8]  *= z;
    e[1] *= x;  e[5] *= y;  e[9]  *= z;
    e[2] *= x;  e[6] *= y;  e[10] *= z;
    e[3] *= x;  e[7] *= y;  e[11] *= z;
    return this;
  };
/**
 * 设置平移矩阵。
 * @param x The X value of a translation.
 * @param y The Y value of a translation.
 * @param z The Z value of a translation.
 * @return this
 */
 Matrix4.prototype.setTranslate = function(x, y, z) {
    var e = this.elements;
    e[0] = 1;  e[4] = 0;  e[8]  = 0;  e[12] = x;
    e[1] = 0;  e[5] = 1;  e[9]  = 0;  e[13] = y;
    e[2] = 0;  e[6] = 0;  e[10] = 1;  e[14] = z;
    e[3] = 0;  e[7] = 0;  e[11] = 0;  e[15] = 1;
    return this;
  };
  
  /**
   * 将矩阵从右平移。
   * @param x The X value of a translation.
   * @param y The Y value of a translation.
   * @param z The Z value of a translation.
   * @return this
   */
  Matrix4.prototype.translate = function(x, y, z) {
    var e = this.elements;
    e[12] += e[0] * x + e[4] * y + e[8]  * z;
    e[13] += e[1] * x + e[5] * y + e[9]  * z;
    e[14] += e[2] * x + e[6] * y + e[10] * z;
    e[15] += e[3] * x + e[7] * y + e[11] * z;
    return this;
  };
/**
 * 设置矩阵缩放。
 * @param x The scale factor along the X axis
 * @param y The scale factor along the Y axis
 * @param z The scale factor along the Z axis
 * @return this
 */
 Matrix4.prototype.setScale = function(x, y, z) {
    var e = this.elements;
    e[0] = x;  e[4] = 0;  e[8]  = 0;  e[12] = 0;
    e[1] = 0;  e[5] = y;  e[9]  = 0;  e[13] = 0;
    e[2] = 0;  e[6] = 0;  e[10] = z;  e[14] = 0;
    e[3] = 0;  e[7] = 0;  e[11] = 0;  e[15] = 1;
    return this;
  };
/**
 * 乘以矩阵从右边旋转。
 * 旋转轴的矢量可能没有归一化。
 * @param angle The angle of rotation (degrees)
 * @param x The X coordinate of vector of rotation axis.
 * @param y The Y coordinate of vector of rotation axis.
 * @param z The Z coordinate of vector of rotation axis.
 * @return this
 */
 Matrix4.prototype.rotate = function(angle, x, y, z) {
    return this.concat(new Matrix4().setRotate(angle, x, y, z));
  };
/**
 * 设置旋转矩阵。
 * 旋转轴的矢量可能没有归一化
 * @param angle The angle of rotation (degrees)
 * @param x The X coordinate of vector of rotation axis.
 * @param y The Y coordinate of vector of rotation axis.
 * @param z The Z coordinate of vector of rotation axis.
 * @return this
 */
 Matrix4.prototype.setRotate = function(angle, x, y, z) {
    var e, s, c, len, rlen, nc, xy, yz, zx, xs, ys, zs;
  
    angle = Math.PI * angle / 180;
    e = this.elements;
  
    s = Math.sin(angle);
    c = Math.cos(angle);
  
    if (0 !== x && 0 === y && 0 === z) {
      // Rotation around X axis
      if (x < 0) {
        s = -s;
      }
      e[0] = 1;  e[4] = 0;  e[ 8] = 0;  e[12] = 0;
      e[1] = 0;  e[5] = c;  e[ 9] =-s;  e[13] = 0;
      e[2] = 0;  e[6] = s;  e[10] = c;  e[14] = 0;
      e[3] = 0;  e[7] = 0;  e[11] = 0;  e[15] = 1;
    } else if (0 === x && 0 !== y && 0 === z) {
      // Rotation around Y axis
      if (y < 0) {
        s = -s;
      }
      e[0] = c;  e[4] = 0;  e[ 8] = s;  e[12] = 0;
      e[1] = 0;  e[5] = 1;  e[ 9] = 0;  e[13] = 0;
      e[2] =-s;  e[6] = 0;  e[10] = c;  e[14] = 0;
      e[3] = 0;  e[7] = 0;  e[11] = 0;  e[15] = 1;
    } else if (0 === x && 0 === y && 0 !== z) {
      // Rotation around Z axis
      if (z < 0) {
        s = -s;
      }
      e[0] = c;  e[4] =-s;  e[ 8] = 0;  e[12] = 0;
      e[1] = s;  e[5] = c;  e[ 9] = 0;  e[13] = 0;
      e[2] = 0;  e[6] = 0;  e[10] = 1;  e[14] = 0;
      e[3] = 0;  e[7] = 0;  e[11] = 0;  e[15] = 1;
    } else {
      // Rotation around another axis
      len = Math.sqrt(x*x + y*y + z*z);
      if (len !== 1) {
        rlen = 1 / len;
        x *= rlen;
        y *= rlen;
        z *= rlen;
      }
      nc = 1 - c;
      xy = x * y;
      yz = y * z;
      zx = z * x;
      xs = x * s;
      ys = y * s;
      zs = z * s;
  
      e[ 0] = x*x*nc +  c;
      e[ 1] = xy *nc + zs;
      e[ 2] = zx *nc - ys;
      e[ 3] = 0;
  
      e[ 4] = xy *nc - zs;
      e[ 5] = y*y*nc +  c;
      e[ 6] = yz *nc + xs;
      e[ 7] = 0;
  
      e[ 8] = zx *nc + ys;
      e[ 9] = yz *nc - xs;
      e[10] = z*z*nc +  c;
      e[11] = 0;
  
      e[12] = 0;
      e[13] = 0;
      e[14] = 0;
      e[15] = 1;
    }
  
    return this;
  };

/**
 * 设置单位向量
 * @returns this
 */

Matrix4.prototype.setIdentity=function(){
    var e=this.elements;
    e[0] = 1;   e[4] = 0;   e[8]  = 0;   e[12] = 0;
    e[1] = 0;   e[5] = 1;   e[9]  = 0;   e[13] = 0;
    e[2] = 0;   e[6] = 0;   e[10] = 1;   e[14] = 0;
    e[3] = 0;   e[7] = 0;   e[11] = 0;   e[15] = 1;
    return this
}
/**
 * @param {number} index 不传index2就是索引,传index2，index是行
 * @param {number} index2 列
 */
Matrix4.prototype.getElement=function(index,index2){
    if(index2==undefined){
        return this.elements[index]
    }else{
        return this.elements[index*4+index2]
    }
}
/**
 * @returns {Matrix4} 创建一个对象
 */
Matrix4.createObj=function(){
    return new Matrix4();
}
//------------------------ Vector2 ------------------------------
export var Vector2=function(x,y){
    if(typeof x=='number'){
        this.x=x;
    }else{
        this.x=0
    }
    if(typeof y=='number'){
        this.y=y;
    }else{
        this.y=0;
    }
}
Vector2.zero=new Vector2(0,0);
/**
 * 向量加法
 * @param {Vector} vec1 
 * @param {Vector} vec2 
 * @returns {Vector2} 
 */
Vector2.add=function(vec1,vec2){
    return new Vector2(vec1.x+vec2.x,vec1.y+vec2.y);
}
// void Rotate2(double x1, double y1, double alpha, double& x2, double& y2)
// {
// 	x2 = x1 * cos(alpha) - y1 * sin(alpha);
// 	y2 = x1 * sin(alpha) + y1 * cos(alpha);
// }
/**
 * 
 * @param {Vector2} vec1 
 * @param {Vector2} origin 
 * @param {*} alphe 
 * @returns 
 */
Vector2.rotate=function(vec1,origin ,alphe){
    vec1.x = origin.x * Math.cos(alphe) - origin.y*Math.sin(alphe);
    vec1.y = origin.x * Math.sin(alphe) - origin.y*Math.cos(alphe);
    return vec1;
}
/**
 * 向量减法
 * @param {Vector} vec1 被减数
 * @param {Vector} vec2 减数
 * @returns {Vector2} 返回一个Vector2对象
 */
Vector2.sub=function(vec1,vec2){
    return new Vector2(vec1.x-vec2.x,vec1.y-vec2.y);
}
/**
 *  向量与常量乘法
 * @param {number} multiple 常量
 * @param {Vector2} value 向量
 * @returns 结果返回新的的向量
 */
Vector2.ride=function(multiple,value){
    return new Vector2(value.x*multiple,value.y*multiple);;
}
/**
 *  向量与常量乘法
 * @param {number} multiple 常量
 * @param {Vector2} value 向量
 * @returns 结果返回新的的向量
 */
 Vector2.prototype.ride=function(value){
    this.x*=value;
    this.y*=value;
    return this;
}
/**
 * 向量过程
 * @param {Vector} from 开始
 * @param {Vector} to 目标
 * @param {number} process [0,1]过程
 * @returns {Vector2} 返回一个新的向量
 */
Vector2.lerp=function(from,to,process){
    let res=new Vector2();
    res.x=from.x+process*(to.x-from.x)
    res.y=from.y+process*(to.y-from.y)
    return res;
}
/**
 * 向量过程
 * @param {Vector} to 目标
 * @param {number} process [0,1]过程
 * @returns this
 */
 Vector2 .prototype.lerp=function(to,process){
    this.x=this.x+process*(to.x-this.x)
    this.y=this.y+process*(to.y-this.y)
    return this;
}
/**
 * 归一化
 * @returns {Vector2} 
 */
Vector2.prototype.normalize=function(){
    let len=this.magnitude();
    this.x/=len;
    this.y/=len;
    return this;
}
/**
 * 获取向量的模
 */
Vector2.prototype.magnitude=function(){
    return Math.sqrt(Math.pow(this.y,2)+Math.pow(this.x,2));
}
/**
 * 获取向量差的模
 * @returns number
 */
 Vector2.magnitude=function(vec,vec2){
    return Math.sqrt(Math.pow((vec.x-vec2.x),2)+Math.pow((vec.y-vec2.y),2));
}



//------------------------ Vector3 ------------------------------
export var Vector3=function(x,y,z){
    if(typeof x=='number'){
        this.x=x;
    }else{
        this.x=0
    }
    if(typeof y=='number'){
        this.y=y;
    }else{
        this.y=0;
    }
    if(typeof z=='number'){
        this.z=z;
    }else{
        this.z=0;
    }
}
/**
 * 向量加法
 * @param {Vector} vec1 
 * @param {Vector} vec2 
 * @returns {Vector3} 返回新的值
 */
Vector3.add=function(vec1,vec2){
    return new Vector3(vec1.x+vec2.x,vec1.y+vec2.y,vec1.z+vec2.z);
}
/**
 * 向量减法
 * @param {Vector} vec1 被减数
 * @param {Vector} vec2 减数
 * @returns {Vector3} 返回一个Vector2对象
 */
Vector3.sub=function(vec1,vec2){
    return new Vector3(vec1.x-vec2.x,vec1.y-vec2.y,vec1.z-vec2.z);
}
/**
 *  向量与常量乘法
 * @param {number} multiple 常量
 * @param {Vector3} value 向量
 * @returns 结果返回新的的向量
 */
Vector3.ride=function(multiple,value){
    return new Vector3(value.x*multiple,value.y*multiple,value.z*multiple);
}
/**
 * 向量过程
 * @param {Vector} from 开始
 * @param {Vector} to 目标
 * @param {number} process [0,1]过程
 * @returns {Vector3} 返回一个新的向量
 */
Vector3.lerp=function(from,to,process){
    let res=new Vector3();
    res.x=from.x+process*(to.x-from.x)
    res.y=from.y+process*(to.y-from.y)
    res.z=from.z+process*(to.z-from.z)
    return res;
}
/**
 * 归一化
 * @returns {Vector3} 
 */
Vector2.prototype.normalize=function(){
    let len=this.magnitude();
    this.x/=len;
    this.y/=len;
    this.z/=len;
    return this;
}
/**
 * 获取向量的模
 */
Vector3.prototype.magnitude=function(){
    return Math.sqrt(Math.pow(this.y,2)+Math.pow(this.x,2)+Math.pow(this.z,2));
}

//------------------------ Vector4 ------------------------------ 
export var  Vector4=function(x,y,z,w){
    if(typeof x=='number'){
        this.x=x;
    }else{
        this.x=0
    }
    if(typeof y=='number'){
        this.y=y;
    }else{
        this.y=0;
    }
    if(typeof z=='number'){
        this.z=z;
    }else{
        this.z=0;
    }
    if(typeof w=='number'){
        this.w=w;
    }else{
        this.w=0;
    }
}
/**
 * 向量加法
 * @param {Vector4} vec1 
 * @param {Vector4} vec2 
 * @returns {Vector4} 返回新的值
 */
Vector4.add=function(vec1,vec2){
    return new Vector4(vec1.x+vec2.x,vec1.y+vec2.y,vec1.z+vec2.z,vec1.w,+vec2.w);
}
/**
 * 向量减法
 * @param {Vector} vec1 被减数
 * @param {Vector} vec2 减数
 * @returns {Vector4} 返回一个Vector4对象
 */
Vector4.sub=function(vec1,vec2){
    return new Vector4(vec1.x-vec2.x,vec1.y-vec2.y,vec1.z-vec2.z,vec1.w-vec2.w);
}
/**
 *  向量与常量乘法
 * @param {number} multiple 常量
 * @param {Vector4} value 向量
 * @returns 结果返回新的的向量
 */
Vector4.ride=function(multiple,value){
    return new Vector4(value.x*multiple,value.y*multiple,value.z*multiple,value.w*multiple);
}
/**
 * 向量过程
 * @param {Vector4} from 开始
 * @param {Vector4} to 目标
 * @param {number} process [0,1]过程
 * @returns {Vector4} 返回一个新的向量
 */
Vector4.lerp=function(from,to,process){
    let res=new Vector4();
    res.x=from.x+process*(to.x-from.x)
    res.y=from.y+process*(to.y-from.y)
    res.z=from.z+process*(to.z-from.z)
    res.w=from.w+process*(to.w-from.w)
    return res;
}
/**
 * 向量过程
 * @param {Vector4} to 目标
 * @param {number} process [0,1]过程
 */
 Vector4.prototype.lerp=function(to,process){
    this.x=this.x+process*(to.x-this.x)
    this.y=this.y+process*(to.y-this.y)
    this.z=this.z+process*(to.z-this.z)
    this.w=this.w+process*(to.w-this.w)
}
/**
 * 归一化
 * @returns {Vector4} 
 */
Vector4.prototype.normalize=function(){
    let len=this.magnitude();
    this.x/=len;
    this.y/=len;
    this.z/=len;
    this.w/=len;
    return this;
}
/**
 * 获取向量的模
 */
Vector4.prototype.magnitude=function(){
    return Math.sqrt(Math.pow(this.y,2)+Math.pow(this.x,2)+Math.pow(this.z,2)+Math.pow(this.w,2));
}




